import crypto from 'crypto-js'
import isNull from 'lodash/isNull'
import isUndefined from 'lodash/isUndefined'

/**
 * aes 加解密开关， YES：开启， NO：关闭
 * @type {boolean}
 */
let enabled = false
/**
 * 密钥：32位
 * @type {string}
 */
let sk = ''
/**
 * 固定IV：16位
 * @type {string}
 */
let iv = ''

/**
 * 设置 aes 加解密开关
 * process.env.VUE_APP_AES_ENABLED='YES'  // 环境变量指定加解密开关
 * @param value {string} YES：开启， NO：关闭
 */
const setEnabled = (value) => {
  enabled = value === 'YES'
}
const isEnabled = () => enabled || process.env.VUE_APP_AES_ENABLED === 'YES'

/**
 * 设置密钥：32位
 * process.env.VUE_APP_AES_SECRET_KEY='VnlSwQROeLeaZyXYqKFzdWmtsYseGwEF'  // 环境变量指定加解密密钥
 * @param value {string}
 */
const setSecretKey = (value) => {
  // console.log(['setSecretKey', value])
  sk = crypto.enc.Utf8.parse(value)
}
const getSecretKey = () => {
  if (!sk) {
    if (process.env.VUE_APP_AES_SECRET_KEY) {
      sk = crypto.enc.Utf8.parse(process.env.VUE_APP_AES_SECRET_KEY)
    }
  }
  return sk
}

/**
 * 设置固定IV：16位
 * process.env.VUE_APP_AES_IV='2022010100112299'  // 环境变量指定加解密固定IV
 * @param value {string}
 */
const setIV = (value) => {
  // console.log(['setIV', value])
  iv = value ? crypto.enc.Utf8.parse(value) : ''
}
const getIV = () => {
  if (!iv) {
    if (process.env.VUE_APP_AES_IV) {
      iv = crypto.enc.Utf8.parse(process.env.VUE_APP_AES_IV)
    }
  }
  return iv
}

/**
 * 加密
 * @param plaintext {string} 明文串
 * @return {string} base64字符串
 */
const encrypt = (plaintext) => {
  if (!isEnabled()) {
    return plaintext
  }
  if (isNull(plaintext) || isUndefined(plaintext) || plaintext === '') {
    return plaintext
  }
  if (getIV()) { // 静态 IV 加密
    return crypto.AES.encrypt(
      crypto.enc.Utf8.parse(plaintext),
      getSecretKey(),
      {
        mode: crypto.mode.CBC,
        padding: crypto.pad.Pkcs7,
        iv: getIV()
      }
    ).toString()
  }
  // 动态 IV 加密
  const ivRandom = `000${new Date().getTime()}`
  const encryptDataBase64 = crypto.AES.encrypt(
    crypto.enc.Utf8.parse(plaintext),
    getSecretKey(),
    {
      mode: crypto.mode.CBC,
      padding: crypto.pad.Pkcs7,
      iv: crypto.enc.Utf8.parse(ivRandom)
    }
  ).toString()
  const ivBuffer = Buffer.from(ivRandom)
  // 拼接 IV 和密文数据包
  return Buffer.concat([ivBuffer, Buffer.from(encryptDataBase64, 'base64')]).toString('base64')
}
/**
 * 解密
 * @param encryptText {string} 密文串
 * @return {string} 明文字符串
 */
const decrypt = (encryptText) => {
  if (!isEnabled()) {
    return encryptText
  }
  if (isNull(encryptText) || isUndefined(encryptText) || encryptText === '') {
    return encryptText
  }
  if (getIV()) { // 静态 IV 解密
    return crypto.AES.decrypt(encryptText, getSecretKey(), {iv: getIV()}).toString(crypto.enc.Utf8)
  }
  // 动态 IV 解密
  const buffer = Buffer.from(encryptText, 'base64')
  const ivRandom = crypto.enc.Utf8.parse(buffer.slice(0, 16).toString()) // 动态 IV
  const dataBase64 = buffer.slice(16).toString('base64') // 密文数据包
  return crypto.AES.decrypt(dataBase64, getSecretKey(), {iv: ivRandom}).toString(crypto.enc.Utf8)
}
/**
 * process.env.VUE_APP_AES_ENABLED='YES'  // 环境变量指定加解密开关
 * process.env.VUE_APP_AES_SECRET_KEY='VnlSwQROeLeaZyXYqKFzdWmtsYseGwEF'  // 环境变量指定加解密密钥
 * process.env.VUE_APP_AES_IV='2022010100112299'  // 环境变量指定加解密固定IV
 */
export default {
  setEnabled,
  setSecretKey,
  setIV,
  encrypt,
  decrypt
}
